using System;
using System.Security.Principal;

namespace KodeIT.Web
{
    /// <summary>
    /// This class represents the event raised by IIS when is has successfully completed authentication.
    /// The authenticated account, at this stage, is available for inspection. If your HttpFilter should 
    /// be notified for this event, it should subscribe for the <see cref="IFilterEvents.AuthComplete"/> event.
    /// </summary>
    /// <remarks>
    /// This event allows you to view the method, URL, version, or headers, or to modify the headers sent from the client. 
    /// The <see cref="IFilterEvents.AuthComplete"/> event is sent after the client's identity has been negotiated with 
    /// the client, or when the client is anonymous. Because of the timing of this event, the AUTH_USER server variable 
    /// can be used to reliably obtain the identity of the user. All authentication scheme processes should result in 
    /// either <see cref="IFilterEvents.AuthComplete"/> event, giving the HttpFilter the identity of the user to be 
    /// impersonated, or the <see cref="IFilterEvents.AccessDenied"/> event, when the user is not recognized by the system. 
    /// The <see cref="IFilterEvents.AuthComplete"/> event may be used for:
    /// <list type="bullet">
    ///     <item>
    ///         <term>Accessing the identity of the user to be impersonated.</term>
    ///     </item>
    ///     <item>
    ///         <term>Actions that can be done in the <see cref="IFilterEvents.PreProcHeaders"/> event, such as viewing, altering or removing the request headers.</term>
    ///     </item>
    /// </list>
    /// </remarks>
    public class AuthCompleteEvent : RequestHeadersEvent, IDisposable
    {
        private IntPtr _token;
        private WindowsIdentity _identity;
        private bool _disposed;

        internal AuthCompleteEvent(NativeContext nativeContext, IntPtr token)
            : base(nativeContext)
        {
            _token = token;
        }

        /// <summary>
        /// Gets the the Windows Identity that IIS impersonates when processing the request.
        /// </summary>
        public WindowsIdentity LogonUser
        {
            get
            {
                if (null == _identity)
                {
                    string logonUser = ServerVariables[ServerVariable.LOGON_USER];
                    string authType = ServerVariables[ServerVariable.AUTH_TYPE];
                    bool isAuthenticated =
                        !String.IsNullOrEmpty(logonUser) ||
                        (!String.IsNullOrEmpty(authType) && !authType.ToLower().Equals("basic"));

                    _identity = new WindowsIdentity(
                        _token,
                        String.IsNullOrEmpty(authType) ? String.Empty : authType,
                        WindowsAccountType.Normal,
                        isAuthenticated);
                }

                return _identity;
            }
        }

        #region IDisposable Members

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    if (null != _identity)
                    {
                        _identity.Dispose();
                    }
                }

                _disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
